/*
1.detect ac220 zero cross point
2.read the the level of the ADC,
3.depend on the level , delay some ms to drive moc3052 on and off in order to open TRIAC 
4.finish the process and go to IDLE status.

 ZERO_CROSS_detect P54
 ADC_input 				 P55
 TRIGGER_input     P33
 OUTPUT_PIN 		   P32

*/

#include <stc8g.h>
#include <intrins.h>

#define POWER_OFF   0
#define POWER_ON    1

#define OUTPUT_PIN P32

#define IDLE 0
#define WAIT_ZEROCROSS 1
#define READ_ADC       4
#define DLY_TIME			 5	

#define EX2         0x10

volatile unsigned int zero_cross_count = 0;  // 
volatile unsigned long last_zero_cross_time = 0;  // 
volatile bit valid_zero_cross = 0;  // 
volatile bit trigger_flag = 0;  // 

int status=IDLE;
int timer0_count=0;
code unsigned char phase_table[6]={50,40,35,22,10,1}; //for 100us couter value
unsigned char phase_index=0;
unsigned char cross=0;

void Delay2ms(void)	//@11.0592MHz
{
	unsigned char data i, j;

	i = 29;
	j = 183;
	do
	{
		while (--j);
	} while (--i);
}

void Delay100us(unsigned char delt)	//@11.0592MHz
{
	unsigned char data i,j;


	i = 2*delt;
	j = 109;
	do
	{
		while (--j);
	} while (--i);
}

void ac220_zerocross_EX2_Isr() interrupt 10
{
	if (status==WAIT_ZEROCROSS){
			cross+=1;
			if (cross==3){
				 INTCLKO = 0x00;    //disable ex2 interrupt  
				 Delay100us(phase_table[phase_index]); //delay time depend on the ADC result
				 OUTPUT_PIN=POWER_ON;
				 Delay2ms();
				 OUTPUT_PIN=POWER_OFF;				 
				 status=DLY_TIME; 
				 cross=0;
			}

  }	
}


void press_EX1_Isr() interrupt 2
{
  EX1 = 0;        //INT1 disable
	if(P33==0)
	  status=READ_ADC;	
	else
		status=IDLE;
}


void ADC_Init(void) {
    P5M0 &= ~0x20; 
	  P5M1 |= 0x20;  //P55 high impendence input 
    ADC_CONTR = 0x80;  // open ADC power
    ADC_CONTR |= 0x05;  // P55 is the ADC5 channel
  	ADCCFG = 0x20;		//right aline res(b9,b8),resl(b7b6b5b4b3b2b1b0)
	  ADCTIM = 0x2c;			//CSSETUP(0), CSHOLD(1), SMPDUTY(12)
	  ADC_RES = 0;  // ??ADC?????
    ADC_RESL = 0;
}	

unsigned int ADC_Read(void) {
	unsigned int temp;
    ADC_CONTR |= 0x40;  // ??ADC??
	  _nop_();
    _nop_();
    while (!(ADC_CONTR & 0x20));  // ??????
    ADC_CONTR &= ~0x20;  // ????????
	 temp=ADC_RES*256+ADC_RESL;
    return (temp);  //
}

main()
{
		int i=0;
	  P3M1=0xf0; //P33 bi-dirction ;P32 PUSH and PULL
		P3M0=0x04; 
    P3PU |= 0x08; //p33 up res
	  OUTPUT_PIN=POWER_OFF;
		P5M0 &= ~0x10; P5M1 &= ~0x10; 
	  ADC_Init();
		INTCLKO = 0;    //INT2 disable
	  IT1 = 1;        //INT1 fall down interrupt
    EX1 = 0;        //INT1 enable  
    EA = 1;
		for(i=0;i<500;i++)  Delay2ms();
	  status=IDLE;	
		while(1){
		 switch(status){
			 case IDLE:    	EX1 = 1;   		//INT1 enable  
											INTCLKO = 0;  //INT2 disable
											break;
			 case READ_ADC: phase_index=(unsigned char)(6*ADC_Read()/1024.0);
				              status=WAIT_ZEROCROSS;
			                INTCLKO = EX2;  //enable ex2 interrupt 		 
											break;
			 case DLY_TIME:
											for(i=0;i<196;i++)  Delay2ms(); //delay 400ms for next trigger action
			  							status=IDLE;
											break;
			 
			 default: break;
		 }
			 
		}
	
}